package com.zdw.demo.controller;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.zdw.common.constant.common.CommonConstants;
import com.zdw.common.parent.JSONResult;
import com.zdw.demo.config.international.InternationalUtils;
import com.zdw.demo.config.pay.ReqDecryption;
import com.zdw.demo.dto.WechatOrderParam;
import com.zdw.demo.dto.WechatRefundParam;
import com.zdw.demo.service.WechatPayService;
import com.zdw.demo.vo.WechatCallbackResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;


/**
 * 微信支付 控制器
 * Controller : 控制器类
 * 用于对请求的内容、响应的内容进行数据格式转换。
 */
@Slf4j
@RestController
public class WechatPayController {

    @Autowired
    private WechatPayService wechatPayService;

    /**
     * 1:获取支付二维码(创建订单)
     *
     * @param params 参数
     * @return
     * @throws IOException
     */
    @PostMapping(value = "/wechatpay/createOrder", produces = "application/json")
    public JSONResult createOrder(@RequestBody WechatOrderParam params) {
        JSONResult jsonResult = new JSONResult();
        if (StrUtil.isEmpty(params.getOutTradeNo())
                || StrUtil.isEmpty(params.getDescription())
                || ObjectUtil.isEmpty(params.getTotal())
                || StrUtil.isEmpty(params.getAppName())
                || StrUtil.isEmpty(params.getSecretKey())
        ) {
            return jsonResult.markFail(InternationalUtils.getInternational("wechat.pay.paramsNotExist"), false, 500);
        }
        if (params.getTotal() <= 0) {
            return jsonResult.markFail(InternationalUtils.getInternational("wechat.pay.totalMustGreaterThanZero"), false, 500);
        }
        if (StrUtil.isEmpty(checkSecretKey(params.getSecretKey()))) {
            return jsonResult.markFail(InternationalUtils.getInternational("wechat.pay.illegal"), false, 500);
        }
        return wechatPayService.createOrder(params.getOutTradeNo(), params.getDescription(), params.getTotal(), params.getAppName());
    }

    /**
     * 2:支付回调接口
     */
    @PostMapping(value = "/wechatpay/callback", produces = "application/json")
    public WechatCallbackResult callback(HttpServletRequest request, HttpServletResponse response) {
        return wechatPayService.callback(request, response);
    }

    /**
     * 步骤3:微信支付订单查询接口
     * 作用1:查询订单信息
     * 作用2:已支付则回调应用系统
     *
     * @param transactionId 微信支付订单号
     */
    @GetMapping(value = "/wechatpay/queryOrderByWechat", produces = "application/json")
    public JSONResult queryOrderByWechat(@RequestParam String transactionId, @RequestParam String secretKey) {
        if (StrUtil.isEmpty(checkSecretKey(secretKey))) {
            return new JSONResult().markFail(InternationalUtils.getInternational("wechat.pay.illegal"), false, 500);
        }
        return wechatPayService.queryOrderByWechat(transactionId);
    }

    /**
     * 4:商户订单查询接口
     * 作用1:查询订单信息
     * 作用2:已支付则回调应用系统
     *
     * @param outTradeNo 内部订单号
     */
    @GetMapping(value = "/wechatpay/queryOrderByInner", produces = "application/json")
    public JSONResult queryOrderByInner(@RequestParam String outTradeNo, @RequestParam String secretKey) {
        if (StrUtil.isEmpty(checkSecretKey(secretKey))) {
            return new JSONResult().markFail(InternationalUtils.getInternational("wechat.pay.illegal"), false, 500);
        }
        return wechatPayService.queryOrderByInner(outTradeNo);
    }

    /**
     * 5:关闭订单接口
     *
     * @param param
     */
    @PostMapping(value = "/wechatpay/closeOrder", produces = "application/json")
    public JSONResult closeOrder(@RequestBody WechatOrderParam param) {
        JSONResult jsonResult = new JSONResult();
        if (StrUtil.isEmpty(param.getOutTradeNo()) || StrUtil.isEmpty(param.getSecretKey())) {
            return jsonResult.markFail(InternationalUtils.getInternational("wechat.pay.paramsNotExist"), false, 500);
        }
        if (StrUtil.isEmpty(checkSecretKey(param.getSecretKey()))) {
            return jsonResult.markFail(InternationalUtils.getInternational("wechat.pay.illegal"), false, 500);
        }
        return wechatPayService.closeOrder(param.getOutTradeNo());
    }

    /**
     * 6:订单回调通知(手动执行)
     * 作用1:已支付则回调应用系统
     * 作用2:超过失效时间未支付的待支付订单,更新为关闭状态
     */
    @GetMapping(value = "/wechatpay/notifyOrder", produces = "application/json")
    public JSONResult notifyOrder(@RequestParam String secretKey) {
        if (StrUtil.isEmpty(checkSecretKey(secretKey))) {
            return new JSONResult().markFail(InternationalUtils.getInternational("wechat.pay.illegal"), false, 500);
        }
        return wechatPayService.notifyOrder();
    }

    /**
     * 7:退款接口
     * 支持部分退款,有并发风险
     */
    @PostMapping(value = "/wechatpay/refund", produces = "application/json")
    public JSONResult refund(@RequestBody WechatRefundParam param) throws IOException {
        if (StrUtil.isEmpty(checkSecretKey(param.getSecretKey()))) {
            return new JSONResult().markFail("非法请求");
        }
        if (StrUtil.isEmpty(param.getOutRefundNo())) {
            return new JSONResult().markFail("退款单号不能为空,请检查");
        }
        if (StrUtil.isEmpty(param.getTransactionId()) || StrUtil.isEmpty(param.getOutTradeNo())) {
            return new JSONResult().markFail("微信订单号或内部订单号不能同时为空,请检查");
        }
        if (param.getRefund() <= 0) {
            return new JSONResult().markFail("退款金额不能小于等于0,请检查");
        }
        return wechatPayService.refund(param);
    }

    /**
     * 8:退款通知回调
     */
    @PostMapping(value = "/wechatpay/refundCallback", produces = "application/json")
    public WechatCallbackResult refundCallback(HttpServletRequest request, HttpServletResponse response) throws IOException {
        return wechatPayService.refundCallback(request, response);
    }

    /**
     * 9:内部/商户退款单号查询退款接口
     *
     * @param outRefundNo 内部/商户退款订单号
     */
    @GetMapping(value = "/wechatpay/queryRefund", produces = "application/json")
    public JSONResult queryRefund(@RequestParam String outRefundNo, @RequestParam String secretKey) throws IOException {
        if (StrUtil.isEmpty(checkSecretKey(secretKey))) {
            return new JSONResult().markFail("非法请求");
        }
        return wechatPayService.queryRefund(outRefundNo);
    }

    /**
     * 安全校验
     *
     * @param secretKey
     * @return
     */
    private String checkSecretKey(String secretKey) {
        return ReqDecryption.getReqUserId(secretKey, CommonConstants.REQ_ENCODE_KEY);
    }

    /**
     * XOR操作结合密钥预处理字符串
     *
     * @param input
     * @param key
     * @return
     */
    private static String preprocessWithKey(String input, String key) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            char k = key.charAt(i % key.length());
            sb.append((char) (c ^ k));  // XOR操作
        }
        return sb.toString();
    }

    /**
     * 加密测试
     *
     * @param args
     */
    public static void main(String[] args) {
        String originalString = "zhuo_dw,20241010141530";
        String key            = "kbzhifu";
        // 使用XOR操作结合密钥预处理字符串
        String preprocessedString = preprocessWithKey(originalString, key);
        // 将预处理后的字符串转换为字节数组，并使用Base64编码
        String encodedString = Base64.getEncoder().encodeToString(preprocessedString.getBytes(StandardCharsets.UTF_8));
        System.out.println("Base64编码后的字符串: " + encodedString);
    }

}
